--===========================================================================--
-- Naziv		: Pipeline
-- Ime fajla	: pipeline.vhdl  
-- Verzija		: 0.1
--===========================================================================-- 

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity pipeline is 
	  port (
		--IN
			mrReset,clk,clk2 : in  std_logic ;
		--INOUT
			I_DBUS : in std_logic_vector (15 downto 0); --Data magistrala za instrukcije
			D_DBUS : inout std_logic_vector (15 downto 0); --Data magistrala za podatke 			
		--OUT
			I_RD : out std_logic;
			I_ABUS : out std_logic_vector (15 downto 0); --Adresna magistrala za instrukcije 
			D_RD, D_WR : out std_logic;
			D_ABUS : out std_logic_vector (15 downto 0) --Adresna magistrala za podatke
		
	  );
end;

architecture pipeline_AR of pipeline is
--Komponente:
	--i_fetch faza
	component i_fetch is 
		  port (
			--IN
			   reset,clk : in  std_logic ;
			   stall,branch  : in std_logic;
			   newPC : in std_logic_vector (15 downto 0 );		   
			--BUFFER
			   PC_if : buffer std_logic_vector (15 downto 0 );
			--OUT
			   I_ABUS : out std_logic_vector (15 downto 0); --Adresna magistrala za instrukcije
			   I_RD : out std_logic --Kontrolna magistrala za instrukcije, signal read
		  );
    end component;
	------
	--id faza
	component id is 
		port(
			--IN
				reset,clk : in std_logic;
				flush,stall : in std_logic;              
				PC_if       : in std_logic_vector (15 downto 0 );  --PC iz fetch faze
				I_DBus   : in std_logic_vector(15 downto 0);           -- Instrukcija na data magistrali iz IMem
			--OUT	
				PC_id    : out std_logic_vector (15 downto 0 ); --PC iz fetch faze; PC se mora prosledjivati
				R1_id,R2_id,R3_id     : out std_logic_vector (3 downto 0 );
				Imm_id         : out std_logic_vector (7 downto 0 );
				opcode_id          :out std_logic_vector(4 downto 0)
			   
		);
	end component;
	--------
	--o_fetch faza
	component o_fetch is 
		port(
		   --IN
			reset,clk : in std_logic;
			flush,stall : in std_logic;   
			PC_id    : in std_logic_vector (15 downto 0 ); --PC iz fetch faze; PC se mora prosledjivati
			R1_id,R2_id,R3_id     : in std_logic_vector (3 downto 0 );
			Imm_id         : in std_logic_vector (7 downto 0 );
			opcode_id      : in std_logic_vector(4 downto 0);
		 
		  --OUT
			PC_of              : out std_logic_vector (15 downto 0 );
			R1_of,R2_of,R3_of     : out std_logic_vector(3 downto 0);
			Imm_of             : out std_logic_vector (7 downto 0 );
			opcode_of          : out std_logic_vector(4 downto 0)
		);
	end component;
	--------
	--reg 
	component reg is 
		port(
		  --IN
		   reset,clk,clk2      : in  std_logic;
		   opcode_of   		   : in std_logic_vector(4 downto 0);
		   R1_of,R2_of,R3_of   : in std_logic_vector(3 downto 0);	
		   Reg_wb              : in std_logic_vector(3 downto 0); 
		   Data_wb             : in std_logic_vector(15 downto 0);
		   write_wb            : in std_logic;
		   
		 --OUT
		   Reg1,Reg2,Reg3   : out std_logic_vector(15 downto 0);
		   stall         	: buffer std_logic;
		   flush_ex 	    : out std_logic;
		   D_ABUS           : out std_logic_vector (15 downto 0);--Adresna magistrala za podatke
		   D_DBUS           : out std_logic_vector(15 downto 0);--Data magistrala za podatke
		   D_RD,D_WR  		: out std_logic --Kontrolna magistrala za podatke
		);
	end component;
	--------
	--ex 
	component ex is 
		port(
		   --IN
		    reset,clk,clk2  : in std_logic;
			PC_of           : in std_logic_vector (15 downto 0 );
			R1_of,R2_of,R3_of     : in std_logic_vector (3 downto 0 );
			Reg1,Reg2,Reg3  : in std_logic_vector (15 downto 0 ); --dolaze iz registarskog fajla
			Imm_of          : in std_logic_vector (7 downto 0 );
			opcode_of       : in std_logic_vector(4 downto 0);
			flush_ex  		: in std_logic;
			D_DBUS          : in std_logic_vector(15 downto 0);--Podatak koji dolazi iz DMem
			
		  --Buffer-pogledaj zasto
			opcode_ex       : buffer std_logic_vector(4 downto 0);
		  --OUT
			branch          : out std_logic;
			result          : out std_logic_vector (15 downto 0 );
			R1_ex,R2_ex,R3_ex     : out std_logic_vector (3 downto 0 );
			newPC           : out std_logic_vector (15 downto 0 );
			stackOverflow   : out std_logic	;
			D_DBUS_ex       : out std_logic_vector(15 downto 0)		
		);
	end component;
	--------
	--wb 
	component wb is 
		port(
		 --IN
			reset,clk 	  : in  std_logic; 
			result         : in std_logic_vector (15 downto 0 );
			opcode_ex      : in std_logic_vector(4 downto 0);
			R1_ex,R2_ex,R3_ex     : in std_logic_vector (3 downto 0 );
			D_DBUS_ex          : in std_logic_vector(15 downto 0);
		   
		  --OUT
			Reg_wb              : out std_logic_vector(3 downto 0); 
			Data_wb           : out std_logic_vector(15 downto 0);
			write_wb            : out std_logic
		);
	end component;
	--------

--Signali
	--ex:i_fetch 
	signal  branch: std_logic;--ovo je flush za ID i O_FETCH faze
	signal	newPC :  std_logic_vector (15 downto 0 );
	--i_fetch:id 
	signal	PC_if :  std_logic_vector (15 downto 0 ); 
	--id:o_fetch 
	signal  PC_id :  std_logic_vector (15 downto 0 ); --PC iz fetch faze; PC se mora prosledjivati
	signal	R1_id,R2_id,R3_id     : std_logic_vector (3 downto 0 );
	signal	Imm_id         : std_logic_vector (7 downto 0 );
	signal	opcode_id      : std_logic_vector(4 downto 0);
	--o_fetch:reg,ex
	signal  R1_of,R2_of,R3_of     : std_logic_vector(3 downto 0);
	--o_fetch:ex
	signal  PC_of              : std_logic_vector (15 downto 0 );
	signal  Imm_of             : std_logic_vector (7 downto 0 );
	signal	opcode_of          : std_logic_vector(4 downto 0);
	--reg:ex
	signal  Reg1,Reg2,Reg3     : std_logic_vector(15 downto 0);
	signal  flush_ex :std_logic;
	--ex:wb
	signal  opcode_ex     : std_logic_vector(4 downto 0);
	signal  result     : std_logic_vector(15 downto 0);
	signal  R1_ex,R2_ex,R3_ex     : std_logic_vector (3 downto 0 );
	signal  D_DBUS_ex       : std_logic_vector(15 downto 0);	
	--ex:pipeline
	signal  stackOverflow :std_logic;
	--wb:reg
	signal	Reg_wb              : std_logic_vector(3 downto 0); 
	signal	Data_wb           : std_logic_vector(15 downto 0);
	signal	write_wb            : std_logic;
	--reg:i_fetch,id,o_fetch
	signal  stall :std_logic;
	--pipeline
	signal  reset :std_logic;
	
begin

	--povezivanje i_fetch
	  i_fetch_map : i_fetch PORT MAP (reset,clk,stall,branch,newPC,PC_if,I_ABUS,I_RD);
    --povezivanje id
	  id_map      :  id     PORT MAP (reset,clk,branch,stall,PC_if,I_DBUS,PC_id,R1_id,R2_id,R3_id,Imm_id,opcode_id);
	--povezivanje o_fetch
	  o_fetch_map : o_fetch PORT MAP (reset,clk,branch,stall,PC_id,R1_id,R2_id,R3_id,Imm_id,opcode_id,PC_of,R1_of,R2_of,R3_of,Imm_of,opcode_of);
	--povezivanje reg
      reg_map 	  : reg		PORT MAP (reset,clk,clk2,opcode_of,R1_of,R2_of,R3_of,Reg_wb,Data_wb,write_wb,Reg1,Reg2,Reg3,stall,flush_ex,D_ABUS,D_DBUS,D_RD,D_WR);
    --povezivanje ex
      ex_map 	  : ex		PORT MAP (reset,clk,clk2,PC_of,R1_of,R2_of,R3_of,Reg1,Reg2,Reg3,Imm_of,opcode_of,flush_ex,D_DBUS,opcode_ex,branch,result,R1_ex,R2_ex,R3_ex,newPC,stackOverflow,D_DBUS_ex);
    --povezivanje ex
      wb_map 	  : wb		PORT MAP (reset,clk,result,opcode_ex,R1_ex,R2_ex,R3_ex,D_DBUS_ex,Reg_wb,Data_wb,write_wb);
       
    reset<=mrReset or stackOverflow;
    
end pipeline_AR;